package jia.core.state;

import jia.core.Compass;
import jia.core.Module;
import jia.core.Space;
import jia.core.Wall;
import jia.core.flags.WallFlags;

import javax.vecmath.Vector2d;

/**
 * This class represents the current state of the player at any given time.  It keeps track
 * with where the player is in the module, what direction they are facing, as well as what direction
 * they can travel.  Since there is no side to side movement without changing their orientation,
 * only move forward and move backward are implemented.
 *
 * @author Alec Lanter
 */
public class BasicPlayerState implements PlayerState{
	private Vector2d position;
	private Module module;
	private Compass facing;

	/**
	 * Returns what direction the player is facing
	 *
	 * @see net.sf.jia.framework.state.PlayerState#getFacing()
	 */
	public Compass getFacing(){
		return facing;
	}

	/**
	 * Sets a new facing direction for the Player.  This is sometimes done as the result of
	 * an event, such as a Teleport.
	 *
	 * @see net.sf.jia.framework.state.PlayerState#setFacing(net.sf.jia.framework.Compass)
	 */
	public void setFacing(Compass facing){
		this.facing = facing;
	}

	/**
	 * Returns the Players position from the map
	 *
	 * @see net.sf.jia.framework.state.PlayerState#getPosition()
	 */
	public Vector2d getPosition(){
		return position;
	}

	/**
	 * Sets the player to a new position on the map, possibly as the result of a teleport spell
	 * or a pit trap.
	 *
	 * @see net.sf.jia.framework.state.PlayerState#setPosition(javax.vecmath.Vector2d)
	 */
	public void setPosition(Vector2d pos){
		this.position = pos;
	}

	/**
	 * Returns the current module for the given player state.  Each game can consist of many
	 * modules, so this is important to be able to change or retrieve.
	 *
	 * @see net.sf.jia.framework.state.PlayerState#getCurrentModule()
	 */
	public Module getCurrentModule(){
		return module;
	}

	/**
	 * Moves the player forward
	 *
	 * @see net.sf.jia.framework.state.PlayerState#moveForward()
	 */
	public void moveForward(){
		int dx = 0;
		int dy = 0;
		switch(facing.getDirectionalValue()) {
			case Compass.NORTH_VAL:
				if(isPassable(Compass.NORTH)) {
					dy = -1;
				}
				break;
			case Compass.SOUTH_VAL:
				if(isPassable(Compass.SOUTH)) {
					dy = 1;
				}
				break;
			case Compass.EAST_VAL:
				if(isPassable(Compass.EAST)) {
					dx = 1;
				}
				break;
			case Compass.WEST_VAL:
				if(isPassable(Compass.WEST)) {
					dx = -1;
				}
		}
		position.x += dx;
		position.y += dy;
	}

	/**
	 * Checks to see if the direction the player is attempting to go is passable or not.
	 *
	 * @param wallDir
	 *
	 * @return
	 */
	protected boolean isPassable(Compass wallDir){
		Space currentSpace = module.getSpace(position);
		Wall testWall = currentSpace.getWall(wallDir);
		if(testWall != null) {
			return testWall.getFlags().hasFlag(WallFlags.OPEN);
		} else {
			return true;
		}
	}

	/**
	 * Moves the player backward
	 *
	 * @see net.sf.jia.framework.state.PlayerState#moveBackward()
	 */
	public void moveBackward(){
		int dx = 0;
		int dy = 0;
		switch(facing.getDirectionalValue()) {
			case Compass.NORTH_VAL:
				if(isPassable(Compass.SOUTH)) {
					dy = -1;
				}
				break;
			case Compass.SOUTH_VAL:
				if(isPassable(Compass.NORTH)) {
					dy = 1;
				}
				break;
			case Compass.EAST_VAL:
				if(isPassable(Compass.WEST)) {
					dx = 1;
				}
				break;
			case Compass.WEST_VAL:
				if(isPassable(Compass.EAST)) {
					dx = -1;
				}
		}
		position.x -= dx;
		position.y -= dy;
	}

	/**
	 * Sets the module for the current player state.
	 *
	 * @see net.sf.jia.framework.state.PlayerState#setCurrentModule(net.sf.jia.framework.Module)
	 */
	public void setCurrentModule(Module module){
		this.module = module;
		this.position = module.getDefaultEntryPoint().getEntryPosition();
		this.facing = module.getDefaultEntryPoint().getEntryFacing();
	}
}
